package com.hq.talk.http;

import android.content.Context;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import com.hq.lib_comview.common.utils.DesUtils;
import com.hq.lib_comview.common.utils.NetUtil;
import com.hq.lib_comview.common.utils.StringUtils;
import com.hq.lib_comview.common.utils.SystemUtils;
import com.hq.lib_cookie.ClearableCookieJar;
import com.hq.lib_cookie.PersistentCookieJar;
import com.hq.lib_cookie.cache.SetCookieCache;
import com.hq.lib_cookie.persistence.SharedPrefsCookiePersistor;
import com.hq.talk.BuildConfig;
import com.hq.talk.app.App;
import com.hq.talk.common.Session;
import com.hq.talk.http.request.APIService;
import com.litesuits.common.assist.Network;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManagerFactory;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by JS01 on 2016/6/7.
 */
public class Http {

    private static OkHttpClient client;
    private static OkHttpClient mSignclient;
    //用户，账户，好友
    private static APIService mNewPayService;
    //用户，账户，好友
    private static APIService mUserService;
    //红包，打赏
    private static APIService mRedService;
    //圈子,作品
    private static APIService mCircleService;
    //晒一晒
    private static APIService mShineService;
    //叶浩地址--调支付,提现（做签名认证）
    private static APIService mAddSignService;
    //请求头中的token值
    public static String headToken = null;
    //记录传过来的act值
    public static String actionCode;

    /**
     * 调试支付，设置的暂时地址连接叶浩电脑
     *
     * @return
     */
    public static APIService getAddSignService(Context context, String act) {
//        if (mSignclient == null || isReCreateClient() || !TextUtils.equals(sign, actionCode)) {
        String sign = DesUtils.encrypt(act + "." + Session.getUserId()).replace("\\s", "").replace("\n", "");
        initPaySignClient(context, sign);
//            actionCode = act;
//        }
//        if (mAddSignService == null) {
        String base_url = "";
        if (App.isFlag == 1) {
            base_url = API.URL_APP_USER_RELEASE;
        } else if (App.isFlag == 2) {
            base_url = API.URL_APP_USER_TEST;
        }
        Retrofit retrofit = new Retrofit.Builder()
                .client(mSignclient)
                .baseUrl(base_url)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        mAddSignService = retrofit.create(APIService.class);
//        }
        return mAddSignService;
    }

    /**
     * 初始化OKHttpClient,处理支付和提现的sign
     */
    private static void initPaySignClient(Context context, String sign) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
//        if (!App.isDebug) {
        //开启日志拦截器
        setLoggingInterceptor(builder);
//        }
        setCookieJar(builder);
        setSignHeaderInterceptor(context, builder, sign);
        //setParamsInterceptor(builder);
        setCacheDirectory(builder);
        setCacheInterceptor(builder);
        setTimeout(builder);
        //setCertificates(builder,context);
        mSignclient = builder.build();
    }

    /**
     * 头部拦截器
     *
     * @param builder
     */
    private static void setSignHeaderInterceptor(final Context mContent, OkHttpClient.Builder builder, final String sign) {
        Log.d("huangqiang", "setSignHeaderInterceptor");
//        if (builder != null) {
        Interceptor headerInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                headToken = Session.getUserToken();
                Log.d("huangqiang", "setSignHeaderInterceptor Session.getSessionKey()  " + headToken);
                Request originalRequest = chain.request();
                Log.d("Http_sign---", sign);
                Request.Builder requestBuilder = originalRequest.newBuilder()
                        .header("devType", "2")
//                            .header("AppType", "POST")
//                            .header("Content-Type", "application/json")
//                            .header("Accept", "application/json")
                        .header("sign", sign);
                Log.d("huangqiang", "setSignHeaderInterceptor headToken is " + headToken);
                if (!TextUtils.isEmpty(headToken)) {
                    requestBuilder.header("token", headToken);
                }
                requestBuilder.header("appVersion", BuildConfig.VERSION_NAME);
                requestBuilder.header("apiVersion", "V2.0.0");
                requestBuilder.header("devName", Build.MODEL);
                requestBuilder.header("devId", StringUtils.isEmpty(SystemUtils.getIMEI(mContent)) ? "" : SystemUtils.getIMEI(mContent));
                requestBuilder.header("ip", SystemUtils.getIp(mContent));
                requestBuilder.header("net", NetUtil.getNetWorkState(mContent) + "");
//                requestBuilder.header("devType", "2");
                requestBuilder.method(originalRequest.method(), originalRequest.body());
                Request request = requestBuilder.build();
                return chain.proceed(request);
            }
        };
        builder.addInterceptor(headerInterceptor);
//        }
    }


    public static boolean isReCreateClient() {
//        String loginToken = Session.getSessionKey();
//        if (TextUtils.isEmpty(headToken)) {
//            if (TextUtils.isEmpty(loginToken)) {
//                return false;
//            } else {
//                return true;
//            }
//        } else {
//            if (TextUtils.isEmpty(loginToken)) {
//                return true;
//            } else {
//                return !headToken.equals(loginToken);
//            }
//        }
        return false;
    }

    /**
     * 返回用户，账户，好友
     * APIService的对象，访问接口
     */
    public static APIService getUserService(Context context) {
        if (client == null || isReCreateClient()) {
            initClient(context);
        }
        if (mUserService == null) {
            String base_url = "";
            if (App.isFlag == 1) {
                base_url = API.URL_APP_USER_RELEASE;
            } else if (App.isFlag == 2) {
                base_url = API.URL_APP_USER_TEST;
            }
            Retrofit retrofit = new Retrofit.Builder()
                    .client(client)
                    .baseUrl(base_url)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            mUserService = retrofit.create(APIService.class);
        }
        return mUserService;
    }

    /**
     * 返回红包，打赏,首页
     * APIService的对象，访问接口
     */
    public static APIService getRedPacketService(Context context) {
        if (client == null || isReCreateClient()) {
            initClient(context);
        }
        if (mRedService == null) {
            String base_url = "";
            if (App.isFlag == 1) {
                base_url = API.URL_APP_REDPACKET_RELEASE;
            } else if (App.isFlag == 2) {
                base_url = API.URL_APP_REDPACKET_TEST;
            }
            Retrofit retrofit = new Retrofit.Builder()
                    .client(client)
                    .baseUrl(base_url)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            mRedService = retrofit.create(APIService.class);
        }
        return mRedService;
    }

    /**
     * 返回圈子，作品
     * APIService的对象，访问接口
     */
    public static APIService getCircleService(Context context) {
        if (client == null || isReCreateClient()) {
            initClient(context);
        }
        if (mCircleService == null) {
            String base_url = "";
            if (App.isFlag == 1) {
                base_url = API.URL_APP_CIRCLE_RELEASE;
            } else if (App.isFlag == 2) {
                base_url = API.URL_APP_CIRCLE_TEST;
            }
            Retrofit retrofit = new Retrofit.Builder()
                    .client(client)
                    .baseUrl(base_url)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            mCircleService = retrofit.create(APIService.class);
        }
        return mCircleService;
    }


    /**
     * 返回晒一晒
     * APIService的对象，访问接口
     */
    public static APIService getShineService(Context context) {
        if (client == null || isReCreateClient()) {
            initClient(context);
        }
        if (mShineService == null) {
            String base_url = "";
            if (App.isFlag == 1) {
                base_url = API.URL_APP_SHINE_RELEASE;
            } else if (App.isFlag == 2) {
                base_url = API.URL_APP_SHINE_TEST;
            }
            Retrofit retrofit = new Retrofit.Builder()
                    .client(client)
                    .baseUrl(base_url)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            mShineService = retrofit.create(APIService.class);
        }
        return mShineService;
    }

    /**
     * 初始化OKHttpClient
     */
    private static void initClient(Context context) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
//        if (!App.isDebug) {
        //开启日志拦截器
        setLoggingInterceptor(builder);
//        }
        setCookieJar(builder);
        setHeaderInterceptor(context, builder);
        //setParamsInterceptor(builder);
        setCacheDirectory(builder);
        setCacheInterceptor(builder);
        setTimeout(builder);
        setCertificates(builder, context);
        client = builder.build();
    }

    /**
     * 初始化OKHttpClient
     */
    private static void initClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
//        if (App.isDebug) {
        //开启日志拦截器
        setLoggingInterceptor(builder);
//        }
//        setCookieJar(builder);

        setHeaderInterceptor(builder);
//        setParamsInterceptor(builder);
//        setCacheDirectory(builder);
//        setCacheInterceptor(builder);
        setTimeout(builder);
        client = builder.build();
    }

    /**
     * 设置超时和重试
     *
     * @param builder
     */
    private static void setTimeout(OkHttpClient.Builder builder) {
        //设置超时
        builder.connectTimeout(10, TimeUnit.SECONDS);
        builder.readTimeout(15, TimeUnit.SECONDS);
        builder.writeTimeout(15, TimeUnit.SECONDS);
        //错误重连
        builder.retryOnConnectionFailure(true);
    }

    /**
     * 设置https 证书
     *
     * @param builder
     */
    private static void setCertificates(OkHttpClient.Builder builder, Context context) {

        try {
            InputStream inputStream = null;
            // 下载的证书放到项目中的assets目录中
            inputStream = context.getAssets().open("rrzkey.cer");
            CertificateFactory certificateFactory = CertificateFactory
                    .getInstance("X.509");
            Certificate certificate = certificateFactory
                    .generateCertificate(inputStream);
            KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
            keyStore.load(null, null);
            keyStore.setCertificateEntry("trust", certificate);

            TrustManagerFactory trustManagerFactory = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            builder.sslSocketFactory(sslContext.getSocketFactory());
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置缓存路径
     *
     * @param builder
     */
    public static void setCacheDirectory(OkHttpClient.Builder builder) {
        //设置缓存路径
        Context context = App.getContext();
        if (context != null) {
            String path = context.getCacheDir().getPath();
            File httpCacheDirectory = new File(path, "responses");
            Cache cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024);
            builder.cache(cache);
        }
    }

    /**
     * 设置CookieJar
     *
     * @param builder
     */
    private static void setCookieJar(OkHttpClient.Builder builder) {
        Context context = App.getContext();
        if (context != null) {
            ClearableCookieJar cookieJar = new PersistentCookieJar(
                    new SetCookieCache(),
                    new SharedPrefsCookiePersistor(context));
            builder.cookieJar(cookieJar);
        }
    }

    /**
     * 缓存拦截器
     *
     * @param builder
     */
    private static void setCacheInterceptor(OkHttpClient.Builder builder) {
        if (builder != null) {
            Interceptor cacheInterceptor = new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    Context context = App.getContext();
                    if (context != null) {
                        if (!Network.isAvailable(context)) {
                            request = request.newBuilder()
                                    .cacheControl(CacheControl.FORCE_CACHE)
                                    .build();
                        }

                        Response response = chain.proceed(request);
                        if (Network.isAvailable(context)) {
                            int maxAge = 0;
                            // 有网络时,设置缓存超时时间0个小时
                            response.newBuilder()
                                    .header("Cache-Control", "public, max-age=" + maxAge)
                                    .removeHeader("Pragma")
                                    .build();
                        } else {
                            // 无网络时,设置超时为4周
                            int maxStale = 60 * 60 * 24 * 3;
                            response.newBuilder()
                                    .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                                    .removeHeader("Pragma")
                                    .build();
                        }
                        return response;
                    } else {
                        //默认当作有网络处理
                        int maxAge = 0;
                        Response response = chain.proceed(request);
                        response.newBuilder()
                                .header("Cache-Control", "public, max-age=" + maxAge)
                                .removeHeader("Pragma")
                                .build();
                        return response;
                    }
                }
            };
            builder.addInterceptor(cacheInterceptor);
        }
    }

    /**
     * 公共参数拦截器
     *
     * @param builder
     */
    private static void setParamsInterceptor(OkHttpClient.Builder builder) {
        if (builder != null) {
            Interceptor paramsInterceptor = new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request originalRequest = chain.request();
                    Request request;
                    String method = originalRequest.method();
                    Headers headers = originalRequest.headers();
                    HttpUrl modifiedUrl = originalRequest.url().newBuilder()
                            .addQueryParameter("platform", "android")
                            .addQueryParameter("version", "1.0.0")
                            .build();
                    request = originalRequest.newBuilder().url(modifiedUrl).build();
                    return chain.proceed(request);
                }
            };
            builder.addInterceptor(paramsInterceptor);
        }
    }

    /**
     * 头部拦截器
     *
     * @param builder
     */
    private static void setHeaderInterceptor(OkHttpClient.Builder builder) {
        Log.d("token", "setHeaderInterceptor");
        if (builder != null) {
            Interceptor headerInterceptor = new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    headToken = Session.getUserToken();
                    Log.d("token", "setHeaderInterceptor Session.getSessionKey()  " + headToken + "-------");
                    Request originalRequest = chain.request();
                    Request.Builder requestBuilder = originalRequest.newBuilder()
                            .header("devType", "2");
//                            .header("Content-Type", "application/json")
//                            .header("Accept", "application/json")
//                            .header("token", "1")
//                            .header("sign", "1");
                    Log.d("token", "setHeaderInterceptor headToken is " + headToken);
//                    if (!TextUtils.isEmpty(headToken)) {
//                    requestBuilder.header("token", headToken);
//                    }
//                    requestBuilder.header("appVersion", BuildConfig.VERSION_NAME);
//                    requestBuilder.header("apiVersion", "V2.0.0");
//                    requestBuilder.header("devName", Build.MODEL);
                    requestBuilder.method(originalRequest.method(), originalRequest.body());
                    Request request = requestBuilder.build();
                    return chain.proceed(request);
                }
            };
            builder.addInterceptor(headerInterceptor);
        }
    }

    /**
     * 头部拦截器
     *
     * @param builder
     */
    private static void setHeaderInterceptor(final Context mContent, OkHttpClient.Builder builder) {
        Log.d("token", "setHeaderInterceptor");
        if (builder != null) {
            Interceptor headerInterceptor = new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    headToken = Session.getUserToken();
                    Log.d("token", "setHeaderInterceptor Session.getSessionKey()  " + headToken + "-------");
                    Request originalRequest = chain.request();
                    Request.Builder requestBuilder = originalRequest.newBuilder()
                            .header("devType", "2");
//                            .header("Content-Type", "application/json")
//                            .header("Accept", "application/json")
//                            .header("token", "1")
//                            .header("sign", "1");
                    Log.d("token", "setHeaderInterceptor headToken is " + headToken);
//                    if (!TextUtils.isEmpty(headToken)) {
                    requestBuilder.header("token", headToken);
//                    }
                    requestBuilder.header("appVersion", BuildConfig.VERSION_NAME);
                    requestBuilder.header("apiVersion", "V2.0.0");
//                    requestBuilder.header("devName", StringUtils.isEmpty(Build.MODEL) ? "" : Build.MODEL);
//                    requestBuilder.header("devId", StringUtils.isEmpty(SystemUtils.getIMEI(mContent)) ? "" : SystemUtils.getIMEI(mContent));
//                    requestBuilder.header("ip", SystemUtils.getIp(mContent));
//                    requestBuilder.header("net", IntentUtil.getNetType(mContent));
                    requestBuilder.method(originalRequest.method(), originalRequest.body());
                    Request request = requestBuilder.build();
                    return chain.proceed(request);
                }
            };
            builder.addInterceptor(headerInterceptor);
        }
    }

    /**
     * 日志拦截器
     *
     * @param builder
     */
    private static void setLoggingInterceptor(OkHttpClient.Builder builder) {
        if (builder != null) {
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(loggingInterceptor);
        }
    }

    /**
     * GET请求
     *
     * @param url      请求链接
     * @param params   请求参数
     * @param callback 请求回调 为防止内存泄漏，callback用弱引用包装
     */
    public static <T> void get(String url, Map<String, String> params, final RequestCallback<T> callback) {
        if (client == null) {
            initClient();
        }
        final WeakReference<RequestCallback<T>> weakReference = new WeakReference<>(callback);
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                urlBuilder.addQueryParameter(key, value);
            }
        }
        HttpUrl httpUrl = urlBuilder.build();
        final Request request = new Request.Builder()
                .url(httpUrl)
                .cacheControl(CacheControl.FORCE_NETWORK)
                .get()
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                RequestCallback<T> callback1 = weakReference.get();
                if (callback1 != null) {
                    int code = -1;
                    String error = e.getLocalizedMessage();
                    callback1.onFailure(code, error);
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                RequestCallback<T> callback1 = weakReference.get();
                if (response.isSuccessful()) {
                    ResponseBody body = response.body();
                    T t = (T) body.string();
                    if (callback1 != null) {
                        callback1.onSuccess(t);
                    }
                } else {
                    int code = response.code();
                    String error = response.message();
                    if (callback1 != null) {
                        callback1.onFailure(code, error);
                    }
                }
            }
        });
    }

    /**
     * POST请求
     *
     * @param url      请求链接
     * @param params   请求参数
     * @param callback 请求回调 为防止内存泄漏，callback用弱引用包装
     */
    public static <T> void post(String url, Map<String, String> params, final RequestCallback<T> callback) {
        if (client == null || isReCreateClient()) {
            initClient();
        }
        final WeakReference<RequestCallback<T>> weakReference = new WeakReference<>(callback);
        FormBody.Builder bodyBuilder = new FormBody.Builder();
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                bodyBuilder.add(key, value);
            }
        }
        FormBody formBody = bodyBuilder.build();

        Request request = new Request.Builder()
                .cacheControl(CacheControl.FORCE_NETWORK)
                .url(url)
                .post(formBody)
                .build();
        Call call = client.newCall(request);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                RequestCallback<T> callback1 = weakReference.get();
                if (callback1 != null) {
                    int code = -1;
                    String error = e.getLocalizedMessage();
                    callback1.onFailure(code, error);
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                RequestCallback<T> callback1 = weakReference.get();
                if (response.isSuccessful()) {
                    ResponseBody body = response.body();
                    T t = (T) body.string();
                    if (callback1 != null) {
                        callback1.onSuccess(t);
                    }
                } else {
                    int code = response.code();
                    String error = response.message();
                    if (callback1 != null) {
                        callback1.onFailure(code, error);
                    }
                }
            }
        });
    }

    /**
     * POST请求
     *
     * @param url      请求链接
     * @param params   请求参数
     * @param callback 请求回调 为防止内存泄漏，callback用弱引用包装
     */
    public static <T> void post(String url, List<Map<String, String>> params, final RequestCallback<T> callback) {
        if (client == null) {
            initClient();
        }
        final WeakReference<RequestCallback<T>> weakReference = new WeakReference<>(callback);
        FormBody.Builder bodyBuilder = new FormBody.Builder();
        for (Map<String, String> map : params) {
            if (map != null && !map.isEmpty()) {
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    bodyBuilder.add(key, value);
                }
            }
        }
        FormBody formBody = bodyBuilder.build();

        Request request = new Request.Builder()
                .cacheControl(CacheControl.FORCE_NETWORK)
                .url(url)
                .post(formBody)
                .build();
        Call call = client.newCall(request);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                RequestCallback<T> callback1 = weakReference.get();
                if (callback1 != null) {
                    int code = -1;
                    String error = e.getLocalizedMessage();
                    callback1.onFailure(code, error);
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                RequestCallback<T> callback1 = weakReference.get();
                if (response.isSuccessful()) {
                    ResponseBody body = response.body();
                    T t = (T) body.string();
                    if (callback1 != null) {
                        callback1.onSuccess(t);
                    }
                } else {
                    int code = response.code();
                    String error = response.message();
                    if (callback1 != null) {
                        callback1.onFailure(code, error);
                    }
                }
            }
        });
    }
}
